home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
301_01
/
dcuwcu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-28
|
21KB
|
942 lines
/*
* the Hollywood principle: don't call us, we'll call you
*
* This package uses pd mouse routines and Turbo C graphics
* to implement a mouse, menu, and form handler. An application
* program provides the following routines:
* start(ac, av, ep) - initialization
* menu(m, i) - menu m, item i was selected
* button(b, x, y) - unbound button was pressed
* keyboard(key) - keyboard character struck
* timer(t) - a timer has gone off
*
* This package also provides the following interface routines:
* finish() - all done
* add_menu(m, mdef) - add a menu to the system
* menu_state(m, on) - turn a menu on or off
* menu_item(m, i, str) - change a menu item's string
* mouse_state(on) - turn the mouse on or off
* mouse_shape(type, ...) - set the mouse bitmap
* add_timer(t, wait) - add a timer to the system
* form(fdef, argptr,...) - have user fill out a form
*
* Form definition is pretty complicated. It's somewhat like scanf in
* that it uses a format string and %Nd or %Ns to define an input
* field. A %[str] defines an exit button and a %(str) defines a regular
* button. If you select an exit button, you leave the form. A
* regular button has will toggle a value. A '|' in the definition
* string starts a new line.
*
* If no Microsoft compatible mouse driver is installed, it works
* with keyboard input with the following conventions:
* cursor keys control the mouse
* F1 simulates a button 1 key depression (and release)
* F2 will enter a menu, a second F2 leaves it
*
* Copyright Mark A. Johnson, 1989
*/
#include <stdio.h>
#include <graphics.h>
#include <bios.h>
#define SAVE 5000 /* constant sizes */
#define MAXITEM 30
#define MAXMENU 10
#define MAXFORM 20
#define MAXTIMER 10
#define TXT_WD 8 /* text height and width */
#define TXT_HT 8
#define TITLE 't' /* form item types */
#define NUMBER 'd'
#define STRING 's'
#define EXIT 'e'
#define BUTTON 'b'
#define RADIO 'r'
#define ESC 27 /* constants for keyboard handling */
#define ENTER '\r'
#define TAB '\t'
#define F1 256
#define F2 257
#define UP 258
#define DOWN 259
#define LEFT 260
#define RIGHT 261
#define INS_CHR 17 /* editing cursor for forms */
#define MS_PER_TICK 64 /* milliseconds per tick (from bios) */
typedef struct { int wid, ht; char buf[10]; } Mbits;
typedef struct { char type, row, col, radio, size, *str, *data; } Form;
typedef struct { char **item, size, handle, on; } Menu;
typedef struct { char handle; long wait; } Timer;
static char mouse_ptr[] = {
0xFC, 0xFC, 0xF0, 0xF8, 0xDC, 0xCE, 0x07, 0x02
};
static char mouse_cross[] = {
0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18
};
static Mbits mbits = {
7, 7, { 0xFC, 0xFC, 0xF0, 0xF8, 0xDC, 0xCE, 0x07, 0x02, 0, 0 }
};
int Mx, My; /* current mouse coordinates */
static int Mhotx=0, Mhoty=0; /* offset for mouse cursor hotspot */
static int Mshow; /* is mouse showing or not */
static int Mpresent; /* is a mouse present or not */
int Maxx, Maxy; /* graphics driver position range */
int MaxColor; /* graphics driver color range */
int MaxSave; /* keep track of max size save needed */
static char save[SAVE]; /* buffer to save patches of screen */
static char *items[MAXITEM]; /* menu item table */
static int last_item; /* size of menu table */
static Menu menus[MAXMENU]; /* menu descriptor table */
static int last_menu; /* size of menu descriptor table */
static Form forms[MAXFORM]; /* form table */
static int fcnt; /* number of items in the form table */
static char fbuf[100]; /* buffer for the form def'tion string */
static int fwid; /* max width of the form */
static int fht; /* max height of the form */
static int fl, ft, fr, fb; /* form box coordinates */
static char ebuf[100]; /* edit buffer for form item */
static int ebufx; /* index into the edit buffer */
static int edit; /* index of current editable item */
static Timer timers[MAXTIMER]; /* a set of timers */
static int last_timer; /* number of active timers */
static long last_tick; /* last tick of the old ticker */
main(argc, argv, envp) char **argv, **envp; {
int b, x, y;
int driver, mode;
Mx = My = 0;
if ((Mpresent = ms_init()) == 0)
printf("no mouse!\n");
driver = mode = DETECT; /* detect */
initgraph(&driver, &mode, ".");
if (driver < 0) {
printf("cannot open graph driver, driver=%d\n", driver);
exit(1);
}
start(argc, argv, envp);
Maxx = getmaxx();
Maxy = getmaxy();
MaxColor = getmaxcolor();
last_tick = biostime(0, 0L);
if (Mpresent)
mouse_appl();
else key_appl();
}
/* drive the application from the mouse */
static
mouse_appl() {
int b, x, y;
ms_setspeed(10, 10);
ms_hbounds(0, Maxx);
ms_vbounds(0, Maxy);
mouse_state(1);
while (1) {
do_timer();
if (kbhit()) {
mouse_state(0);
keyboard(getch());
mouse_state(1);
}
if (ms_button()) {
delay(50);
if ((b = ms_button()) != 0) {
mouse_state(0);
if (b == 2)
do_menu();
else {
button(b, Mx, My);
while (ms_button())
;
}
mouse_state(1);
}
}
ms_motion(&x, &y);
if (x || y) move_mouse(x, y);
}
}
/* drive the application from the keyboard */
static
key_appl() {
int c, x, y;
mouse_state(1);
while (1) {
do_timer();
if (kbhit()) {
c = key();
if (c == F1) {
mouse_state(0);
button(1, Mx, My);
mouse_state(1);
}
else if (c == F2) {
mouse_state(0);
do_menu();
mouse_state(1);
}
else if (is_arrow(c, &x, &y))
move_mouse(x, y);
else {
mouse_state(0);
keyboard(c);
mouse_state(1);
}
}
}
}
/* change the mouse bitmap */
mouse_shape(type, data, hx, hy) char *data; {
int i;
char *p;
int m_on = Mshow;
if (m_on) mouse_state(0);
switch (type) {
case 0:
p = mouse_ptr;
Mhotx = Mhoty = 0;
break;
case 1:
p = mouse_cross;
Mhotx = Mhoty = 3;
break;
case 2:
p = data;
Mhotx = hx;
Mhoty = hy;
break;
}
for (i = 0; i < 8; i++)
mbits.buf[i] = p[i];
if (m_on) mouse_state(1);
}
/* handle keyboard input, map F1, etc to single keys */
static
key() {
int c;
static int back = 0;
if (back) {
c = back;
back = 0;
}
else {
c = getch();
if (c == 0) {
switch (c = getch()) {
case 59: c = F1; break;
case 60: c = F2; break;
case 72: c = UP; break;
case 80: c = DOWN; break;
case 77: c = RIGHT; break;
case 75: c = LEFT; break;
default: back = c; c = 0; break;
}
}
}
return c;
}
/* is the given key an arrow key, if so, set the delta x,y pointers */
static
is_arrow(c, xp, yp) int c, *xp, *yp; {
static int lastc, cnt;
if (c != lastc) {
lastc = c;
cnt = 1;
}
else cnt++;
*xp = *yp = 0;
switch (c) {
case UP:
*yp = -cnt;
break;
case DOWN:
*yp = cnt;
break;
case LEFT:
*xp = -cnt;
break;
case RIGHT:
*xp = cnt;
break;
default:
return 0;
}
return 1;
}
/* the application requests termination */
finish() {
closegraph();
exit(0);
}
/* move the mouse a bit */
static
move_mouse(dx, dy) {
mouse_state(0);
Mx += dx;
if (Mx < 0) Mx = 0;
if (Mx > Maxx) Mx = Maxx;
My += dy;
if (My < 0) My = 0;
if (My > Maxy) My = Maxy;
mouse_state(1);
}
/* turn the mouse picture on or off */
mouse_state(on) {
if (on ^ Mshow)
putimage(Mx-Mhotx, My-Mhoty, &mbits, XOR_PUT);
Mshow = on;
}
/* add a timer to the system, wait is in milliseconds */
add_timer(handle, wait) long wait; {
int i, j;
long total = 0L;
/* find the insertion point */
for (i = 0; i < last_timer; i++) {
if (wait < total + timers[i].wait)
break;
total += timers[i].wait;
}
/* shuffle things down if necessary */
if (i < last_timer) {
for (j = last_timer; j > i; j--)
timers[j] = timers[j-1];
}
/* insert the new timer, adjust wait to incr over previous */
wait -= total;
timers[i].handle = handle;
timers[i].wait = wait;